package com.vf.cloud.server.signalling.util;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import com.alibaba.fastjson.JSONObject;
import com.jfinal.kit.JsonKit;
import com.jfinal.kit.StrKit;
import com.vf.cloud.common.constant.Cache;
import com.vf.cloud.server.signalling.pool.CachePool;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class SignallingUtil {

	public static void sendPing(ChannelHandlerContext ctx, long time) {
		Map<String, Object> clientConfig = new HashMap<String, Object>();
		clientConfig.put("type", "pong");
		clientConfig.put("time", time);
		send(ctx, JsonKit.toJson(clientConfig));
	}

	public static void sendConfig(ChannelHandlerContext ctx) {
		Map<String, Object> clientConfig = new HashMap<String, Object>();
		clientConfig.put("type", "config");

		if (Cache.relay != null && StrKit.equals("1", Cache.relay.getEnabled())) {
			Map<String, Object> peerConnectionOptions = new HashMap<String, Object>();

			List<Object> iceServers = new LinkedList<Object>();
			Map<String, Object> iceServer = new HashMap<String, Object>();

			List<Object> urls = new LinkedList<Object>();
			urls.add(String.format("stun:%s:%s", Cache.signalling.getSignalingIP(), Cache.relay.getStunPort()));
			urls.add(String.format("turn:%s:%s", Cache.signalling.getSignalingIP(), Cache.relay.getTurnPort()));

			iceServer.put("urls", urls);
			iceServer.put("username", Cache.relay.getUsername());
			iceServer.put("credential", Cache.relay.getPassword());
			iceServers.add(iceServer);

			peerConnectionOptions.put("iceServers", iceServers);
			peerConnectionOptions.put("sdpSemantics", "unified-plan");
			peerConnectionOptions.put("offerExtmapAllowMixed", false);
			clientConfig.put("peerConnectionOptions", peerConnectionOptions);
		} else {
			clientConfig.put("peerConnectionOptions", new HashMap<String, Object>());
		}

		send(ctx, JsonKit.toJson(clientConfig));
	}

	public static void send(ChannelHandlerContext ctx, String json) {
		if (ctx != null) {
			ctx.channel().writeAndFlush(new TextWebSocketFrame(json)).addListener(new ChannelFutureListener() {
				@Override
				public void operationComplete(ChannelFuture future) throws Exception {
					if (future.isSuccess()) {
						// log.info(String.format("-> Streamer:%s", json));
					} else {
						// log.info(String.format("-> Streamer isError :%s", json));
					}
				}
			});
		}
	}

	public static void send(ChannelHandlerContext ctx, JSONObject json) {
		send(ctx, JsonKit.toJson(json));
	}

	public static void playerDisconnected(String eIO) {

	}

	public static void sendFromPlayerToUE(String playerId, JSONObject json) {
		ChannelHandlerContext player = CachePool.getUEById(playerId);
		if (player != null) {
			send(player, JsonKit.toJson(json));
		}
	}

	public static void sendFromUEToPlayer(String playerId, JSONObject rawMsg) {
		ChannelHandlerContext player = CachePool.getPlayerById(playerId);
		if (player != null) {
			send(player, JsonKit.toJson(rawMsg));
		}
	}

	public static void playerConnected(String playerId) {

	}

	/**
	 * 掉线处理
	 * 
	 * @param channelId
	 */
	public static void disconnected(String channelId) {
		String clientType = CachePool.getType(channelId);
		if (StrKit.equals("UE", clientType)) {
			// onStreamerDisconnected();
//			CachePool.killPlayerByUEChannelId(CachePool.getId(channelId),channelId);
			CachePool.removeUECache(channelId);
			log.info(String.format("streamer disconnected:  %s ", channelId));
		} else if (StrKit.equals("EIO", clientType)) {
			onPlayerDisconnected(CachePool.getId(channelId));
			// CachePool.killUEByPlayerChannelId(CachePool.getId(channelId),channelId);
			CachePool.removePlayerCache(channelId);
			log.info(String.format("player disconnected  %s ", channelId));
		}
	}

	/**
	 * 玩家掉线通知UE
	 * 
	 * @param playerId
	 */
	public static void disconnectPlayer(String playerId) {
		JSONObject toUEMsg = new JSONObject();
		toUEMsg.put("type", "close");
		toUEMsg.put("playerId", playerId);
		toUEMsg.put("dataChannel", true);
		toUEMsg.put("sfu", false);
		sendFromPlayerToUE(playerId, toUEMsg);

	}

	/**
	 * 关闭Streamer -》 player
	 * 
	 * @param playerId
	 */
	public static void onStreamerDisconnected(String playerId) {
//		CachePool.killUE(playerId);
//		ChannelHandlerContext player = CachePool.getPlayerById(playerId);
//		if (player != null) {
//			player.close();
//		}
	}

	/**
	 * 玩家掉线
	 * 
	 * @param playerId
	 */
	public static void onPlayerDisconnected(String playerId) {
//		CachePool.killUE(playerId);
//		CachePool.killPayler(playerId);
		JSONObject json = new JSONObject();
		json.put("type", "playerDisconnected");
		json.put("playerId", playerId);
		SignallingUtil.sendFromPlayerToUE(playerId, json);
	}

	public static void sendEvent(ChannelHandlerContext ctx, int code, String msg) {
		Map<String, Object> event = new HashMap<String, Object>();
		event.put("type", "sys_event");
		Map<String, Object> data = new HashMap<String, Object>();
		data.put("code", code);
		data.put("message", msg);
		event.put("data", data);
		send(ctx, JsonKit.toJson(event));
	}

	public static void startStreaming(ChannelHandlerContext ctx) {
		Map<String, Object> event = new HashMap<String, Object>();
		event.put("type", "startStreaming");
		event.put("message", "正在启动云渲染.");
		send(ctx, JsonKit.toJson(event));
	}

	public static void completeStreaming(String playerId) {
		Map<String, Object> event = new HashMap<String, Object>();
		event.put("type", "completeStreaming");
		event.put("message", "云渲染启动完成.");
		ChannelHandlerContext player = CachePool.getPlayerById(playerId);
		if (player != null) {
			send(player, JsonKit.toJson(event));
		}
	}

}
